#include <Ogre.h> 
#include <CEGUI/CEGUI.h> 

#include "include/Gui.h"
#include "include/VectorTest.h"
#include "include/Scripting.h"
#include "include/App.h"


using namespace Ogre;
using namespace Ei;

CEGUI::MouseButton convertOgreButtonToCegui(int buttonID)
{
    switch (buttonID)
    {
    case MouseEvent::BUTTON0_MASK:
        return CEGUI::LeftButton;
    case MouseEvent::BUTTON1_MASK:
        return CEGUI::RightButton;
    case MouseEvent::BUTTON2_MASK:
        return CEGUI::MiddleButton;
    case MouseEvent::BUTTON3_MASK:
        return CEGUI::X1Button;
    default:
        return CEGUI::LeftButton;
    }
}

///////// GUI implementation ////////////////////////////////

Gui::Gui(Ogre::SceneManager* manager, RenderWindow* window) 
{

	mGUIRenderer = new CEGUI::OgreCEGUIRenderer(window, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, manager);
        mGUISystem = new CEGUI::System(mGUIRenderer);
	
	mEventProcessor = new EventProcessor();
	mEventProcessor->initialise(window);
	mEventProcessor->startProcessingEvents();
	 
	mEventProcessor->addMouseMotionListener(this);
        mEventProcessor->addMouseListener(this);
	mEventProcessor->addKeyListener(this);
	
	mGuiEvents = new GuiEvents();	

}
Gui::~Gui()
{	
	mGUIRenderer = NULL;
	mGUISystem   = NULL;
	delete mEventProcessor;
}


/////////////// process input
void Gui::mouseMoved(MouseEvent *e)
{
        CEGUI::System::getSingleton().injectMouseMove(
                e->getRelX() * mGUIRenderer->getWidth(), 
                e->getRelY() * mGUIRenderer->getHeight());
        	
	if (mEventProcessor->getInputReader()->getMouseButton(1))
	{
	  App::sceneMgr()->getSceneNode("Camera")
		->yaw(Degree(e->getRelX() * mGUIRenderer->getWidth() * -0.2));
	  App::sceneMgr()->getSceneNode("Camera_PitchNode")
		->pitch(Degree(e->getRelY() * mGUIRenderer->getWidth() * -0.2));
	}
	
        e->consume();
}

void Gui::mouseDragged (MouseEvent *e) 
{ 
        mouseMoved(e);
}

void  Gui::mousePressed (MouseEvent *e)
{
        CEGUI::System::getSingleton().injectMouseButtonDown(
          convertOgreButtonToCegui(e->getButtonID()));
        e->consume();
}

void  Gui::mouseReleased (MouseEvent *e)
{
        CEGUI::System::getSingleton().injectMouseButtonUp(
          convertOgreButtonToCegui(e->getButtonID()));
        e->consume();
}

void  Gui::keyPressed(KeyEvent* e)
{

        CEGUI::System::getSingleton().injectKeyDown(e->getKey());
		CEGUI::System::getSingleton().injectChar(e->getKeyChar());
        e->consume();
}

void  Gui::keyReleased(KeyEvent* e)
{
	CEGUI::System::getSingleton().injectKeyUp(e->getKey());
	e->consume();
}

void  Gui::keyClicked(KeyEvent* e) 
{
	// Do nothing
	e->consume();
}
	
////////////// frame loop
	
bool Gui::frameStarted(const FrameEvent& evt)
{
				
	//
	// set Settings of mCurrentSample
	//
				   
	// set filter values
	float dt, gamma, msNoise, obNoise;
	dt = Math::Exp( mdt->getScrollPosition()) -1;
	gamma = Math::Exp( mV_GAMMA->getScrollPosition()) -1;
	msNoise = Math::Exp( mV_NOISE->getScrollPosition() ) -1;
	obNoise = Math::Exp( mOBS_NOISE->getScrollPosition()) -1;
	
	String values = "VS: 1: " + StringConverter::toString(Real((Math::Exp(mAccFilterBar->getScrollPosition()) -1) * 0.0001)) +
				   ": 2: " + StringConverter::toString(mAccFilterBar->getScrollPosition()) +
				   ": 3: " + StringConverter::toString(mAccInterAmountBar->getScrollPosition())+
				   ": 4: " + StringConverter::toString(dt) +
				   ": 5: " + StringConverter::toString(gamma) + // Math::Log(dt + 1) gamma
				   ": 6: " + StringConverter::toString(msNoise) +
				   ": 7: " + StringConverter::toString(obNoise) 
				   ;
	
	mValues->setText((CEGUI::utf8*)values.c_str());
	int filterset = 0;

	if(mTuneMag->isSelected())
	{
		App::magAcc()->mSettings["magstation_switch"]  = (Math::Exp(mAccFilterBar->getScrollPosition()) -1) * 0.0001 ;	
		App::magAcc()->mSettings["magstation_max"]  = (Math::Exp(mAccInterStepBar->getScrollPosition()) -1) * 0.0001 ; 
       		App::magAcc()->mSettings["magstation_dt"] = dt;
		App::magAcc()->mSettings["magstation_V_NOISE"] = msNoise;
		App::magAcc()->mSettings["magstation_V_GAMMA"] = gamma;
		App::magAcc()->mSettings["magstation_OBS_NOISE"] = obNoise;
	
		filterset = 1;		
	}
	
	if(mTuneMagMove->isSelected())
	{  
        	App::magAcc()->mSettings["magstation_switch"]  = (Math::Exp(mAccFilterBar->getScrollPosition()) -1) * 0.0001 ;	
		App::magAcc()->mSettings["magstation_max"]  = (Math::Exp(mAccInterStepBar->getScrollPosition()) -1) * 0.0001 ;	
       		App::magAcc()->mSettings["magmove_dt"] = dt;
		App::magAcc()->mSettings["magmove_V_NOISE"] = msNoise;
		App::magAcc()->mSettings["magmove_V_GAMMA"] = gamma;
		App::magAcc()->mSettings["magmove_OBS_NOISE"] = obNoise;
		
		filterset = 2;
	}
	if(mTuneAcc->isSelected())
	{
		App::magAcc()->mSettings["acc_filter"]  = (Math::Exp(mAccInterStepBar->getScrollPosition()) -1) * 0.0001 ; ;
		App::magAcc()->mSettings["acc_interstep"] = mAccInterStepBar->getScrollPosition() + 0.001;
	    	App::magAcc()->mSettings["acc_interamount"]  = mAccInterAmountBar->getScrollPosition()+ 0.001;
        	App::magAcc()->mSettings["acc_dt"] = dt;
		App::magAcc()->mSettings["acc_V_NOISE"] = msNoise;
		App::magAcc()->mSettings["acc_V_GAMMA"] = gamma;
		App::magAcc()->mSettings["acc_OBS_NOISE"] = obNoise;
        	
		filterset = 3;			
	}
	
	App::magAcc()->resetFilters(filterset);
	
	// move camera
	float speed = App::scripting()->getTableFloat("game", "speed");
	// move camera
	 	Quaternion orient = App::sceneMgr()->getCamera("Mono camera")->getDerivedOrientation();
		// move front - back
   	
	    	Vector3 trans = Vector3(0,0,0);
	   	// move front <-> back
      		if (mEventProcessor->getInputReader()->isKeyDown(KC_W)) {                           
	      	 trans = trans + Vector3(0,0,-1  ); }  
       		if (mEventProcessor->getInputReader()->isKeyDown(KC_S) ) {                           
           	 trans = trans + Vector3(0,0,1 );  } 
             	 	
		// Left  <-> right             
        	if (mEventProcessor->getInputReader()->isKeyDown(KC_A)) {                           
           	trans = trans + Vector3(-1 , 0 ,0);}  
        	if (mEventProcessor->getInputReader()->isKeyDown(KC_D)) {                           
		trans = trans + Vector3(1 , 0 ,0);}
		
		trans =  orient * trans;
		trans.y = 0;
		
		// move Up <-> down
        	if (mEventProcessor->getInputReader()->isKeyDown(KC_Q) ) {                           
           	trans = trans + Vector3(0,-1  ,0); }  
        	if (mEventProcessor->getInputReader()->isKeyDown(KC_E)) {                           
           	trans = trans + Vector3(0,1 ,0);} 
		trans.normalise();
		trans = trans * speed;
		App::sceneMgr()->getSceneNode("Camera")->translate(trans);
		Vector3 newPosition= App::sceneMgr()->getSceneNode("Camera")->getWorldPosition();
    		String position = "Camera Position: X: " + StringConverter::toString(newPosition.x) +
				   ": Y " + StringConverter::toString(newPosition.y) +
				   ": Z " + StringConverter::toString(newPosition.z);
				   
              //  mCamPositionWindow->setText((CEGUI::utf8*)position.c_str());
 	   		
		
	return true;		
}

bool Gui::frameEnded(const FrameEvent& evt)
{
	return true;
}

void Gui::init()
{
	
        CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Insane);
        CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme");
        mGUISystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
        CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseMoveCursor");
        mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");
        
        mEditorGuiSheet = CEGUI::WindowManager::getSingleton().loadWindowLayout((CEGUI::utf8*)"VectorEditorLayout.xml");
	mGUISystem->setGUISheet(mEditorGuiSheet);

	mEditorGuiSheet->enable();
	
	// setup special windows and Sliders


	// Sliders
	mAccFilterBar = static_cast<CEGUI::Scrollbar*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/AccFilter"));
	mAccFilterBar->setScrollPosition(0.5);
	mAccInterStepBar = static_cast<CEGUI::Scrollbar*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/InterStep"));
	mAccInterStepBar->setScrollPosition(4);
	mAccInterAmountBar =  static_cast<CEGUI::Scrollbar*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/InterVal"));
	mAccInterStepBar->setScrollPosition(.9);
	
	mdt =  static_cast<CEGUI::Scrollbar*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/dt"));
	mdt->setScrollPosition(.5);
	mV_GAMMA =  static_cast<CEGUI::Scrollbar*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/V_GAMMA"));
	mV_GAMMA->setScrollPosition(.5);
	mV_NOISE =  static_cast<CEGUI::Scrollbar*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/V_NOISE"));
	mV_NOISE->setScrollPosition(.5);
	mOBS_NOISE =  static_cast<CEGUI::Scrollbar*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/OBS_NOISE"));
	mOBS_NOISE->setScrollPosition(.5);
	
	// push buttons
	
		CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/Reinit")->subscribeEvent
	(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&GuiEvents::reinitKalman, mGuiEvents ));
	
		CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/SaveSettings")->subscribeEvent
	(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&GuiEvents::saveSettings, mGuiEvents ));
	
		CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/LoadSettings")->subscribeEvent
	(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&GuiEvents::loadSettings, mGuiEvents ));
	
	mValues = CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"VectorControlsWin/Info9");
	CEGUI::EventArgs temp;
	
	// radio button
	mTuneAcc = static_cast<CEGUI::RadioButton*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"TuneAcc")); 
	mTuneMag = static_cast<CEGUI::RadioButton*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"TuneMag"));
	mTuneMagMove = static_cast<CEGUI::RadioButton*>(CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"TuneMagMove"));

	
	mGuiEvents->loadSettings(temp);
}

void Gui::show(bool toggle)
{
   if (toggle)
   {	mEditorGuiSheet->show(); }
   else
   {   mEditorGuiSheet->hide(); }
}
